//
//  XLRefreshControl.swift
//  SinaProjectTest
//
//  Created by zhanghaifeng on 16/10/30.
//  Copyright © 2016年 BBSWaitting. All rights reserved.
//

import UIKit

// 自定义下拉刷新的状态
private enum XLRefreshType: Int{
    
    // 下拉刷新状态
    case normal = 0
    // 松手就刷新
    case pulling = 1
    // 正在刷新
    case refreshing = 2
    
}


private let XLRefreshControlHeight: CGFloat = 50
// 自定义下拉刷新控件
class XLRefreshControl: UIControl {

    // 记录当前刷新的控件
    private var currentScrollView: UIScrollView?
    
    // 记录当前刷新状态
    private var xlRefreshType: XLRefreshType = .normal{
        
        didSet{
            switch xlRefreshType {
            case .normal:
                print("下拉刷新")
                // 箭头重置 箭头显示  关闭风火轮
                pullDownImageView.isHidden = false
                UIView.animate(withDuration: 0.25, animations: { 
                    // 重置箭头位置
                    self.pullDownImageView.transform = CGAffineTransform.identity
                })
                indicatorView.stopAnimating()
                messageLabel.text = "下拉刷新"
                // 判断上一次刷新状态是正在刷新 让其重置位置
                // old 表示上一次存储的值
                if oldValue == .refreshing {
                    UIView.animate(withDuration: 0.25, animations: {
                        // 设置停留位置 核心代码 重置停留位置
                        self.currentScrollView?.contentInset.top -= XLRefreshControlHeight
                    })
                }
            case .pulling:
                print("松手就刷新")
                // 箭头调转 内容改为 松手就刷新
                UIView.animate(withDuration: 0.25, animations: {
                    // 调转箭头位置
                    self.pullDownImageView.transform = CGAffineTransform(rotationAngle: CGFloat(M_PI))
                })
                messageLabel.text = "松手就刷新"
                
                
            case .refreshing:
                print("正在刷新")
                // 箭头隐藏， 开启风火轮， 内容改成正在刷新
                pullDownImageView.isHidden = true
                indicatorView.startAnimating()
                messageLabel.text = "正在刷新..."
                UIView.animate(withDuration: 0.25, animations: {
                    // 设置停留位置 核心代码
                    self.currentScrollView?.contentInset.top += XLRefreshControlHeight
                })
                // 通知外界刷新数据 核心代码
                sendActions(for: .valueChanged)
                
            }
        }
        
        
        
    }
    
    // 懒加载控件
    // 下拉刷新箭头图片
    fileprivate lazy var pullDownImageView: UIImageView = UIImageView(image: UIImage(named: "tableview_pull_refresh"))
    // 下拉刷新内容label
    fileprivate lazy var messageLabel: UILabel = {
        
        let label = UILabel()
        label.text = "下拉刷新"
        label.font = UIFont.systemFont(ofSize: 11)
        label.textColor = UIColor.gray
        return label
    }()
    // 风火轮
    fileprivate lazy var indicatorView: UIActivityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: .gray)
    
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        // 屏幕的宽度
        let screenWidth = UIScreen.main.bounds.size.width

        self.frame = CGRect(x: 0, y: -XLRefreshControlHeight, width: screenWidth, height: XLRefreshControlHeight)
        
        setupUI()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // 创建视图
    private func setupUI(){
        backgroundColor = UIColor.red
        // 添加控件
        addSubview(pullDownImageView)
        addSubview(messageLabel)
        addSubview(indicatorView)
        
        // 使用系统 布局 autolayout 需要关闭auto
        pullDownImageView.translatesAutoresizingMaskIntoConstraints = false
        messageLabel.translatesAutoresizingMaskIntoConstraints = false
        indicatorView.translatesAutoresizingMaskIntoConstraints = false
        
        // 添加约束
        addConstraint(NSLayoutConstraint(item: pullDownImageView, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 1, constant: -35))
        addConstraint(NSLayoutConstraint(item: pullDownImageView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1, constant: 0))
        
        addConstraint(NSLayoutConstraint(item: messageLabel, attribute: .leading, relatedBy: .equal, toItem: pullDownImageView, attribute: .trailing, multiplier: 1, constant: 0))
        addConstraint(NSLayoutConstraint(item: messageLabel, attribute: .centerY, relatedBy: .equal, toItem: pullDownImageView, attribute: .centerY, multiplier: 1, constant: 0))
        
        addConstraint(NSLayoutConstraint(item: indicatorView, attribute: .centerX, relatedBy: .equal, toItem: pullDownImageView, attribute: .centerX, multiplier: 1, constant: 0))
        addConstraint(NSLayoutConstraint(item: indicatorView, attribute: .centerY, relatedBy: .equal, toItem: pullDownImageView, attribute: .centerY, multiplier: 1, constant: 0))
        // 开启动画
//        indicatorView.startAnimating()
    }
    
    // 获取父控件
    override func willMove(toSuperview newSuperview: UIView?) {
        // 判断是否是可以滚动的控件
        if let scrollView = newSuperview as? UIScrollView{
            // 表示是scrollView的子类 可以监听其滚动
            // 可以使用 KVO 监听他的 contentOffSet 值的改变
            scrollView.addObserver(self, forKeyPath: "contentOffset", options: [.new], context: nil)
            // 记录刷新视图控件
            currentScrollView = scrollView
            
        }
    }
    
    // KVO 监听方法
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        
        guard let scrollView = currentScrollView else {
            return
        }
        // 代码执行到此 表示 scrollView 不为 nil
        // 计算临界带点
        let maxY = -(scrollView.contentInset.top + XLRefreshControlHeight)
        // 获取Y 轴偏移量
        let contentOffSetY = scrollView.contentOffset.y
        // 判断是否拖动
        // 拖动情况下只有两种状态 .normal, pulling
        if scrollView.isDragging{
            // 表示在拖动 判断的核心
            if contentOffSetY < maxY && xlRefreshType == .normal{
                xlRefreshType = .pulling
            } else if contentOffSetY >= maxY && xlRefreshType == .pulling{
                xlRefreshType = .normal
            }
        }else{
            // 表示松手
            if xlRefreshType == .pulling{
                xlRefreshType = .refreshing
            }
        }
    }
    
    // 结束刷新的方法
    func endRefreshing(){
        xlRefreshType = .normal
        
        
    }
    
    deinit {
        // 移除KVO
        currentScrollView?.removeObserver(self, forKeyPath: "contentOffset")
    }

}
